<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    
</body>
<script>
    // function test () {
    //     if (status) {
    //         var status = 'zhuangtai'
    //     } else {
    //         status = '11'
    //         console.log('status', status)
    //     }
    // }
    // test()

    /**
     * 使用var关键词声明的变量存在变量提升，都会被提升到该作用域的最顶部
     * var 的声明具有函数作用域，意味着他们在函数内可见，但在块级内并不会创建新的作用域
     * 全局、函数。在全局作用域中声明var变量，该变量在任何地方都可以被访问到，而且还可以通过window.变量名访问。
     * 如果在函数内部声明变量，那么这个变量就只属于这个函数自己的，外部访问就会报错，最后变量会在函数退出的时候被销毁
     * 块级作用域对于避免变量污染和提高代码的可维护性非常重要。let 和 const 的块级作用域通常更容易预测和管理。
    */

   /**
    * let 不存在变量提升，let生命的变量是在作用域内中生效
    * let 是块级作用域， 所有外面的语句块访问不到
    * 在同一个作用域中禁止重复申明。否则会报错
   */

//   function test2 () {
//     let a = 1 
//     if ( 1 == 1) {
//         let a = 2
//         console.log('a', a)
//     } else {
//         let a = 3
//     }
//     console.log('a', a)
//   }
//   test2()

  /**
   * const 常用来申明常量，常量的值一旦被定义就不允许被修改了
   * 常量一旦被定义的时候就要给初始化值，如果不给就会报错
   * const 也有块级作用域，只能在当前快内有效，也不能在当前作用域中重复申明，也不存在变量提升
   * const 申明对象，虽然const 不能修改指针，但是可以修改值，比如我们定义一个对象，我们九可以修改对象里面的属性值，但是不可以重写整个对象
  */
//  function test3 () {
//     const name = 'lisan'
//     if (1 === 1) {
//         const name = 'wnagsi'
//         console.log('name1', name)
//     } else {
//         const name = 'wangwu'
//     }
//     console.log('name2', name)
//  }
//  test3()

//  const person = {
//     name: 'lisan',
//     age: 20
//  }
//  person.name = 'wangwu'


 // 暂时死区
//  console.log('typeof', typeof value)
//  let value = 20
 /**
  * 暂时性死区的工作原理
  * JavaScript引擎在扫描代码的时候发现声明变量时，如果遇到var就会将它们提升当前作用域的顶端
  * 如果遇到 let const就会将申明放到TDZ，如果访问TDZ中的变量就会抛出错误，只有执行完TDZ中的变量才会将它移出
  * 然后就可以正常使用, 这个机制只在当前作用域中生效
 */
//  console.log('typeof', typeof value)
//  if (true) {
//     let value = 20
//  }

 /**
  * var let const 最大区别
  * var在全局作用域声明的变量会挂载在window对象上，它会创建一个新的全局变量最为全局对象的属性，
  * 这种行为说不定会覆盖到window对象上的某个属性，而let const 不会初夏这个行为
 */
// var a = 1
// function test () {
//     var a = 2
//     if (1 == '1') {
//         var a = 3
//         console.log('a', a)
//     }
//     console.log('a', a)
// }
// test()

let arr = [1, 2, 3, 4, 5];

for (var i = 0; i < arr.length; i++) {
    let result = i
    console.log(result)
};

/**
    8.1.1 var关键字
        var 是传统得变量声明方式，var具有以下特点:
        函数作用域:变量的作用域限制在声明的函数内部，如果在函数外部访问，将会报错。
        变量提升:变量声明会被提升到作用域的顶部，无论声明语句在哪里，都会被视为在作用域的开始处声明的。
        可以重复声明:同一个作用域内，可以多次使用 var 声明同一个变量，后面的声明会覆盖前面的。
        虽然 var 在过去工作中表现良好，但它的作用域机制和变量提升的特性常常导致意外的bug。为了解决这些问题，ES6引入了let和 const。

    8.1.2let关键字
        let:块级作用域的变量声明方式。let 关键字是在ES6中引入的新特性，
        具有以下特点:块级作用域”:使用let 
        声明的变量仅在其所在的代码块内有效，如果在代码块外部访问，将会报错，这种特性有助于提高代码的可读性和可维护性。
        不可重复声明:同一个作用域内，不可以多次使用let 声明同一个变量，否则会报错。
        没有变量提升:let 声明的变是不会被提升到作用域的顶部，只有在声明语句之后才能使用，
    
        8.1.3 const关键字
        const:声明常是得方式，常量的不可修改性可以帮助我们避免错误的赋值操作，提高代码的可靠性。
        const 关键字也是在ES6中引入的新特性，与let 相似，但具有以下特点:
        常量:使用 const 声明的变量是常量，意味着一旦被赋值后，就不能再修改。常量的命名通常使用全大写字母，并采用下划线分隔单词。
        块级作用域:与let 一样，const也具有块级作用域。
        不可重复声明:同一个作用域内，不可以多次使用const 声明同一个变量，否则会报错。
*/
</script>
</html>